package com.rlzy;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

@Configuration
public class TxConfig {
	// 创建事务属性源
		/* 事务拦截类型 */
		@Bean("txSource")
		public TransactionAttributeSource transactionAttributeSource() {
			// 按名称匹配的事务属性源
			NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
			// 只读事务，不做更新操作
			RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
			readOnlyTx.setReadOnly(true);
			readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
			// 当前存在事务就使用当前事务，当前不存在事务就创建一个新的事务
			RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
			// 设置异常
			requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
			// 设置传播行为
			requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
			// 设置隔离级别
			requiredTx.setIsolationLevel(Isolation.REPEATABLE_READ.value());
			requiredTx.setTimeout(5);

			// 事务增强规则
			Map<String, TransactionAttribute> txMap = new HashMap<>();
			txMap.put("add*", requiredTx);
			txMap.put("save*", requiredTx);
			txMap.put("insert*", requiredTx);
			txMap.put("update*", requiredTx);
			txMap.put("delete*", requiredTx);
			txMap.put("get*", readOnlyTx);
			txMap.put("query*", readOnlyTx);
			txMap.put("find*", readOnlyTx);
			txMap.put("login*", readOnlyTx);
			source.setNameMap(txMap);
			return source;
		}

		// 创建事务拦截器
		@Bean("txInterceptor")
		TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx) {
			return new TransactionInterceptor(tx, transactionAttributeSource());
		}

		// 最终产品：创建事务增强者
		@Bean
		public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor) {
			// 创建切面
			AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();
			pointcutAdvisor.setAdvice(txInterceptor); // 注入事务拦截器
			pointcutAdvisor.setExpression("execution (* com.rlzy.service.*.*(..))"); // 注入切面拦截规则
			return pointcutAdvisor;
		}
}
